home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / o_init.c < prev    next >
C/C++ Source or Header  |  1992-12-12  |  9KB  |  341 lines

  1. /*    SCCS Id: @(#)o_init.c    3.1    92/12/11    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include    "hack.h"        /* for typedefs */
  6.  
  7. static void NDECL(setgemprobs);
  8. static void FDECL(shuffle,(int,int,BOOLEAN_P));
  9. static boolean FDECL(interesting_to_discover,(int));
  10.  
  11. /* note that NROFOBJECTS is the number of legal objects, which does not count
  12.  * the strange object and null object that take up positions 0 and NROFOBJECTS+1
  13.  * in the objects array
  14.  */
  15. #define TOTAL_OBJS    (NROFOBJECTS+2)
  16.  
  17. const char obj_symbols[] = {
  18.     ILLOBJ_CLASS, AMULET_CLASS, GOLD_CLASS, FOOD_CLASS, WEAPON_CLASS,
  19.     TOOL_CLASS, BALL_CLASS, CHAIN_CLASS, ROCK_CLASS, ARMOR_CLASS,
  20.     POTION_CLASS, SCROLL_CLASS, WAND_CLASS,
  21.     SPBOOK_CLASS, RING_CLASS, GEM_CLASS, 0 };
  22.  
  23. static short NEARDATA disco[TOTAL_OBJS] = DUMMY;
  24.  
  25. int
  26. letindex(acls) register char acls; {
  27. register int i = 0;
  28. register char ch;
  29.     while ((ch = obj_symbols[i++]) != 0)
  30.         if (ch == acls) return(i);
  31.     return(0);
  32. }
  33.  
  34. static void
  35. setgemprobs()
  36. {
  37.     register int j, first;
  38.     int lev = (ledger_no(&u.uz) > maxledgerno())
  39.                 ? maxledgerno() : ledger_no(&u.uz);
  40.  
  41.     first = bases[letindex(GEM_CLASS)];
  42.  
  43.     for(j = 0; j < 9-lev/3; j++)
  44.         objects[first+j].oc_prob = 0;
  45.     first += j;
  46.     if (first > LAST_GEM || objects[first].oc_class != GEM_CLASS ||
  47.         OBJ_NAME(objects[first]) == NULL) {
  48.         raw_printf("Not enough gems? - first=%d j=%d LAST_GEM=%d",
  49.             first, j, LAST_GEM);
  50.         wait_synch();
  51.         }
  52.     for (j = first; j <= LAST_GEM; j++)
  53.         objects[j].oc_prob = (184+j-first)/(LAST_GEM+1-first);
  54. }
  55.  
  56. /* shuffle descriptions on objects o_low to o_high */
  57. static void
  58. shuffle(o_low, o_high, domaterial)
  59.     register int o_low, o_high;
  60.     register boolean domaterial;
  61. {
  62.     register int i, j;
  63. #ifdef TEXTCOLOR
  64.     int color;
  65. #endif /* TEXTCOLOR */
  66.     register short sw;
  67.  
  68.     for (j=o_low; j <= o_high; j++) {
  69.         i = o_low + rn2(j+1-o_low);
  70.         sw = objects[j].oc_descr_idx;
  71.         objects[j].oc_descr_idx = objects[i].oc_descr_idx;
  72.         objects[i].oc_descr_idx = sw;
  73. #ifdef TEXTCOLOR
  74.         color = objects[j].oc_color;
  75.         objects[j].oc_color = objects[i].oc_color;
  76.         objects[i].oc_color = color;
  77. #endif /* TEXTCOLOR */
  78.         /* shuffle material */
  79.         if (domaterial) {
  80.             sw = objects[j].oc_material;
  81.             objects[j].oc_material = objects[i].oc_material;
  82.             objects[i].oc_material = sw;
  83.         }
  84.     }
  85. }
  86.  
  87. void
  88. init_objects(){
  89. register int i, j, first, last, sum, end;
  90. register char acls;
  91. #ifdef TEXTCOLOR
  92. # define COPY_OBJ_DESCR(o_dst,o_src) \
  93.             o_dst.oc_descr_idx = o_src.oc_descr_idx,\
  94.             o_dst.oc_color = o_src.oc_color
  95. #else
  96. # define COPY_OBJ_DESCR(o_dst,o_src) o_dst.oc_descr_idx = o_src.oc_descr_idx
  97. #endif
  98.  
  99.     /* bug fix to prevent "initialization error" abort on Intel Xenix.
  100.      * reported by mikew@semike
  101.      */
  102.     for (i = 0; i < sizeof(obj_symbols); i++)
  103.         bases[i] = 0;
  104.     /* initialize object descriptions */
  105.     for (i = 0; i < TOTAL_OBJS; i++)
  106.         objects[i].oc_name_idx = objects[i].oc_descr_idx = i;
  107.     init_artifacts();
  108.     /* init base; if probs given check that they add up to 1000,
  109.        otherwise compute probs; shuffle descriptions */
  110.     end = TOTAL_OBJS;
  111.     first = 0;
  112.     while( first < end ) {
  113.         acls = objects[first].oc_class;
  114.         last = first+1;
  115.         while (last < end && objects[last].oc_class == acls) last++;
  116.         i = letindex(acls);
  117.         if ((!i && acls != ILLOBJ_CLASS && acls != VENOM_CLASS) ||
  118.                                 bases[i] != 0)
  119.             error("initialization error for object class %d", acls);
  120.         bases[i] = first;
  121.  
  122.         if (acls == GEM_CLASS) setgemprobs();
  123.     check:
  124.         sum = 0;
  125.         for(j = first; j < last; j++) sum += objects[j].oc_prob;
  126.         if(sum == 0) {
  127.             for(j = first; j < last; j++)
  128.                 objects[j].oc_prob = (1000+j-first)/(last-first);
  129.             goto check;
  130.         }
  131.         if(sum != 1000)
  132.             error("init-prob error for %d (%d%%)", acls, sum);
  133.  
  134.         if (OBJ_DESCR(objects[first]) != NULL &&
  135.            acls != TOOL_CLASS && acls != WEAPON_CLASS && acls != ARMOR_CLASS) {
  136.  
  137.             /* shuffle, also some additional descriptions */
  138.             while (last < end && objects[last].oc_class == acls)
  139.             last++;
  140.             j = last;
  141.             if (acls == GEM_CLASS) {
  142.             if (rn2(2)) { /* change turquoise from green to blue? */
  143.                 COPY_OBJ_DESCR(objects[TURQUOISE],objects[SAPPHIRE]);
  144.             }
  145.             if (rn2(2)) { /* change aquamarine from green to blue? */
  146.                 COPY_OBJ_DESCR(objects[AQUAMARINE],objects[SAPPHIRE]);
  147.             }
  148.             switch (rn2(4)) { /* change fluorite from violet? */
  149.                 case 0:  break;
  150.                 case 1:    /* blue */
  151.                 COPY_OBJ_DESCR(objects[FLUORITE],objects[SAPPHIRE]);
  152.                 break;
  153.                 case 2:    /* white */
  154.                 COPY_OBJ_DESCR(objects[FLUORITE],objects[DIAMOND]);
  155.                 break;
  156.                 case 3:    /* green */
  157.                 COPY_OBJ_DESCR(objects[FLUORITE],objects[EMERALD]);
  158.                 break;
  159.             }
  160.             } else {
  161.             if (acls == POTION_CLASS)
  162.                 j--;  /* only water has a fixed description */
  163.             else if (acls == AMULET_CLASS ||
  164.                  acls == SCROLL_CLASS ||
  165.                  acls == SPBOOK_CLASS)
  166.                 do { j--; }
  167.                 while (!objects[j].oc_magic || objects[j].oc_unique);
  168.             /* non-magical amulets, scrolls, and spellbooks
  169.              * (ex. imitation Amulets, blank, scrolls of mail)
  170.              * and one-of-a-kind magical artifacts at the end of
  171.              * their class in objects[] have fixed descriptions.
  172.              */
  173.             shuffle(first, --j, TRUE);
  174.             }
  175.         }
  176.         first = last;
  177.     }
  178.  
  179.     /* shuffle the helmets */
  180.     shuffle(HELMET, HELM_OF_TELEPATHY, FALSE);
  181.  
  182.     /* shuffle the gloves */
  183.     shuffle(LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY, FALSE);
  184.  
  185.     /* shuffle the cloaks */
  186.     shuffle(CLOAK_OF_PROTECTION, CLOAK_OF_DISPLACEMENT, FALSE);
  187.  
  188.     /* shuffle the boots [if they change, update find_skates() below] */
  189.     shuffle(SPEED_BOOTS, LEVITATION_BOOTS, FALSE);
  190. }
  191.  
  192. /* find the object index for snow boots; used [once] by slippery ice code */
  193. int
  194. find_skates()
  195. {
  196.     register int i;
  197.     register const char *s;
  198.  
  199.     for (i = SPEED_BOOTS; i <= LEVITATION_BOOTS; i++)
  200.     if ((s = OBJ_DESCR(objects[i])) != 0 && !strcmp(s, "snow boots"))
  201.         return i;
  202.  
  203.     impossible("snow boots not found?");
  204.     return -1;    /* not 0, or caller would try again each move */
  205. }
  206.  
  207. void
  208. oinit()            /* level dependent initialization */
  209. {
  210.     setgemprobs();
  211. }
  212.  
  213. void
  214. savenames(fd)
  215. register int fd;
  216. {
  217.     register int i;
  218.     unsigned int len;
  219.  
  220.     bwrite(fd, (genericptr_t)bases, MAXOCLASSES * sizeof *bases);
  221.     bwrite(fd, (genericptr_t)disco, sizeof disco);
  222.     bwrite(fd, (genericptr_t)objects, sizeof(struct objclass) * TOTAL_OBJS);
  223.     /* as long as we use only one version of Hack we
  224.        need not save oc_name and oc_descr, but we must save
  225.        oc_uname for all objects */
  226.     for(i=0; i < TOTAL_OBJS; i++) {
  227.         if(objects[i].oc_uname) {
  228.             len = strlen(objects[i].oc_uname)+1;
  229.             bwrite(fd, (genericptr_t)&len, sizeof len);
  230.             bwrite(fd, (genericptr_t)objects[i].oc_uname, len);
  231.         }
  232.     }
  233. }
  234.  
  235. void
  236. restnames(fd)
  237. register int fd;
  238. {
  239.     register int i;
  240.     unsigned int len;
  241.  
  242.     mread(fd, (genericptr_t) bases, MAXOCLASSES * sizeof *bases);
  243.     mread(fd, (genericptr_t) disco, sizeof disco);
  244.     mread(fd, (genericptr_t) objects, sizeof(struct objclass) * TOTAL_OBJS);
  245.     for(i=0; i < TOTAL_OBJS; i++) {
  246.         if (objects[i].oc_uname) {
  247.             mread(fd, (genericptr_t) &len, sizeof len);
  248.             objects[i].oc_uname = (char *) alloc(len);
  249.             mread(fd, (genericptr_t)objects[i].oc_uname, len);
  250.         }
  251.     }
  252. }
  253.  
  254. void
  255. discover_object(oindx, mark_as_known)
  256. register int oindx;
  257. boolean mark_as_known;
  258. {
  259.     if (!objects[oindx].oc_name_known) {
  260.     register int dindx, acls = objects[oindx].oc_class;
  261.  
  262.     /* Loop thru disco[] 'til we find the target (which may have been
  263.        uname'd) or the next open slot; one or the other will be found
  264.        before we reach the next class...
  265.      */
  266.     for (dindx = bases[letindex(acls)]; disco[dindx] != 0; dindx++)
  267.         if (disco[dindx] == oindx) break;
  268.     disco[dindx] = oindx;
  269.  
  270.     if (mark_as_known) {
  271.         objects[oindx].oc_name_known = 1;
  272.         exercise(A_WIS, TRUE);
  273.     }
  274.     }
  275. }
  276.  
  277. /* if a class name has been cleared, we may need to purge it from disco[] */
  278. void
  279. undiscover_object(oindx)
  280. register int oindx;
  281. {
  282.     if (!objects[oindx].oc_name_known) {
  283.     register int dindx, acls = objects[oindx].oc_class;
  284.     register boolean found = FALSE;
  285.  
  286.     /* find the object; shift those behind it forward one slot */
  287.     for (dindx = bases[letindex(acls)];
  288.           dindx <= NROFOBJECTS && disco[dindx] != 0
  289.         && objects[dindx].oc_class == acls; dindx++)
  290.         if (found)
  291.         disco[dindx-1] = disco[dindx];
  292.         else if (disco[dindx] == oindx)
  293.         found = TRUE;
  294.  
  295.     /* clear last slot */
  296.     if (found) disco[dindx-1] = 0;
  297.     else impossible("named object not in disco");
  298.     }
  299. }
  300.  
  301. static boolean
  302. interesting_to_discover(i)
  303. register int i;
  304. {
  305.     return objects[i].oc_uname != NULL ||
  306.         (objects[i].oc_name_known && OBJ_DESCR(objects[i]) != NULL);
  307. }
  308.  
  309. int
  310. dodiscovered()                /* free after Robert Viduya */
  311. {
  312.     register int i, dis;
  313.     int    ct = 0;
  314.     char class = -1;
  315.     winid tmpwin;
  316.  
  317.     tmpwin = create_nhwindow(NHW_MENU);
  318.     putstr(tmpwin, 0, "Discoveries");
  319.     putstr(tmpwin, 0, "");
  320.  
  321.     for (i = 0; i <= NROFOBJECTS; i++) {
  322.     if ((dis = disco[i]) && interesting_to_discover(dis)) {
  323.         ct++;
  324.         if (objects[dis].oc_class != class) {
  325.         class = objects[dis].oc_class;
  326.         putstr(tmpwin, ATR_INVERSE, let_to_name(class, FALSE));
  327.         }
  328.         putstr(tmpwin, 0, typename(dis));
  329.     }
  330.     }
  331.     if (ct == 0) {
  332.     You("haven't discovered anything yet...");
  333.     } else
  334.     display_nhwindow(tmpwin, TRUE);
  335.     destroy_nhwindow(tmpwin);
  336.  
  337.     return 0;
  338. }
  339.  
  340. /*o_init.c*/
  341.